package cn.yy.common.util;

import cn.yy.common.exception.CustomerException;
import cn.yy.common.web.MessageStatus;
import cn.yy.common.exception.CustomerException;
import cn.yy.common.web.MessageStatus;
import org.apache.commons.io.IOUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/*
 *zip解压缩工具类
 * @author adam
 */
public class ZipUtil {
    /**
     * 只接受图片压缩包   不能包含任何目录的压缩文件  且图片名不能包含中文
     *
     * @param file 前端传入的压缩文件
     * @return 所有图片的base64编码之后的字符串集合
     * @throws CustomerException
     */
    public static List<String> unImageZip(MultipartFile file) throws CustomerException {
        ArrayList<String> list = new ArrayList<>();
        // 获取上传文件的文件名
        String fileName = file.getOriginalFilename();
        //验证文件格式
        verifyZip(fileName);
        //新建保存Zip所用的临时文件
        try {
            File temp_file = File.createTempFile(fileName, null);
            FileOutputStream out = new FileOutputStream(temp_file);

            IOUtils.copy(file.getInputStream(), out);
            out.flush();
            out.close();
            ZipFile zipFile = new ZipFile(temp_file, Charset.forName("GBK"));
            List<? extends ZipEntry> zeList =
                    zipFile.stream()
                            .filter(e -> !e.getName().startsWith("__MACOSX")
                                    && e.getName().indexOf(".DS_Store") == -1)
                            .collect(Collectors.toList());
            for(ZipEntry entry:zeList){
                if(entry.isDirectory()){
                    throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                }else if(!entry.getName().toUpperCase().endsWith(".JPG")&&!entry.getName().toUpperCase().endsWith(".PNG")&&!entry.getName().toUpperCase().endsWith(".JPEG")){
                    throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                }

                InputStream inputStream = zipFile.getInputStream(entry);
                byte[] b = new byte[(int) entry.getSize()];
                //保存到物理机的位置
                //FileOutputStream fos = new FileOutputStream("");

                IOUtils.read(inputStream,b);
                list.add(Base64Util.byte2Base64StringFun(b));
            }


        } catch (IOException e) {
           throw new CustomerException(MessageStatus.SYSTEM_INNER_ERROR);
        }

        return list;
    }

    /**
     * @return 每一个分类名字和其对应的所有图片的base64编码后的字符串
     * @throws CustomerException
     */
    public static Map<String, List<String>> unClassifyAndImageZip(MultipartFile file) throws CustomerException {
        //(vanse)存储子目录和子目录下的图片的base64字符串集合,
        Map<String, List<String>> dirs = new HashMap<>();
        try {
            // 获取上传文件的文件名
            String fileName = file.getOriginalFilename();
            //(vanse)验证文件格式 必须是zip格式
            verifyZip(fileName);

            //(vanse)新建保存Zip所用的临时文件
            File temp_file = File.createTempFile(fileName, null);
            FileOutputStream out = new FileOutputStream(temp_file);
            // (vanse)将数据集压缩文件复制到临时文件中 temp_file
            IOUtils.copy(file.getInputStream(), out);
            out.flush();
            out.close();
            // (vanse) 创建解压缩文件流  指定以GBK解码
            ZipFile zipFile = new ZipFile(temp_file, Charset.forName("GBK"));
            // (vanse) 将压缩文件中的每个条目封装到List<ZipEntry> (筛选后的结果)
            List<? extends ZipEntry> zeList =
                    zipFile.stream()
                            .filter(e -> !e.getName().startsWith("__MACOSX")
                                    && e.getName().indexOf(".DS_Store") == -1)
                            .collect(Collectors.toList());

            for (ZipEntry e : zeList){
                String eName = e.getName();
                // (vanse) 条目名字不能是中文
                ChineseUtil.isContainChinese(eName);
                String[] infos = eName.split("/");
                // (vanse) 如果是目录
                if(infos.length==1){
                    if(!e.isDirectory()){
                        throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                    }
                    //存储目录结构
                    dirs.put(infos[0], new ArrayList<>());
                }else if(infos.length==2){
                    if(!e.getName().toUpperCase().endsWith(".JPG")&&!e.getName().toUpperCase().endsWith(".PNG")&&!e.getName().toUpperCase().endsWith(".JPEG")){
                        throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                    }
                    // (vanse) 如果是文件
                    //存储目录结构
                    List<String> list = dirs.get(infos[0]);
                    // (vanse) 获取每个图片的流
                    InputStream inputStream = zipFile.getInputStream(e);
                    byte[] b = new byte[(int) e.getSize()];
                    // (vanse) 将每个图片读到字节数组中
                    IOUtils.read(inputStream,b);
                    // (vanse) 将图片的字节数组转成base64字符串
                    list.add(Base64Util.byte2Base64StringFun(b));
                    dirs.put(infos[0], list);

                }else{
                    throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        // (vanse) dirs最终存储的是<数据分类,图片base64字符串集合>
        return dirs;
    }

    /**
     * 校验文件是不是zip文件
     *
     * @param fileName 要检验的文件名
     * @throws CustomerException
     */
    public static void verifyZip(String fileName) throws CustomerException {
        if (!fileName.toUpperCase().endsWith(".ZIP")) {
            throw new CustomerException(MessageStatus.FILE_TYPE_ERROR);
        }
    }

    public static Map<String, List<byte[]>> unClassifyAndImageZip2(MultipartFile file) throws CustomerException {
        //(vanse)存储子目录和子目录下的图片的base64字符串集合,
        Map<String, List<byte[]>> dirs = new HashMap<>();
        try {
            // 获取上传文件的文件名
            String fileName = file.getOriginalFilename();
            //(vanse)验证文件格式 必须是zip格式
            verifyZip(fileName);

            //(vanse)新建保存Zip所用的临时文件
            File temp_file = File.createTempFile(fileName, null);
            FileOutputStream out = new FileOutputStream(temp_file);
            // (vanse)将数据集压缩文件复制到临时文件中 temp_file
            IOUtils.copy(file.getInputStream(), out);
            out.flush();
            out.close();
            // (vanse) 创建解压缩文件流  指定以GBK解码
            ZipFile zipFile = new ZipFile(temp_file, Charset.forName("GBK"));
            // (vanse) 将压缩文件中的每个条目封装到List<ZipEntry> (筛选后的结果)
            List<? extends ZipEntry> zeList =
                    zipFile.stream()
                            .filter(e -> !e.getName().startsWith("__MACOSX")
                                    && e.getName().indexOf(".DS_Store") == -1)
                            .collect(Collectors.toList());

            for (ZipEntry e : zeList){
                String eName = e.getName();
                // (vanse) 条目名字不能是中文
                ChineseUtil.isContainChinese(eName);
                String[] infos = eName.split("/");
                // (vanse) 如果是目录
                if(infos.length==1){
                    if(!e.isDirectory()){
                        throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                    }
                    //存储目录结构
                    dirs.put(infos[0], new ArrayList<>());
                }else if(infos.length==2){
                    if(!e.getName().toUpperCase().endsWith(".JPG")&&!e.getName().toUpperCase().endsWith(".PNG")&&!e.getName().toUpperCase().endsWith(".JPEG")){
                        throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                    }
                    // (vanse) 如果是文件
                    //存储目录结构
                    List<byte[]> list = dirs.get(infos[0]);
                    // (vanse) 获取每个图片的流
                    InputStream inputStream = zipFile.getInputStream(e);
                    byte[] b = new byte[(int) e.getSize()];
                    // (vanse) 将每个图片读到字节数组中
                    IOUtils.read(inputStream,b);
                    // (vanse) 将图片的字节数组转成base64字符串
                    //list.add(Base64Util.byte2Base64StringFun(b));
                    list.add(b);
                    dirs.put(infos[0], list);

                }else{
                    throw new CustomerException(MessageStatus.FILE_DIR_FORMAT_ERROR);
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        // (vanse) dirs最终存储的是<数据分类,图片base64字符串集合>
        return dirs;
    }
}

